﻿/*=====================================================================
 * Arquivo:	Collections.cs
 * 
 * Sumário: Implementação de métodos utilitários para Collections.
 * 
 * Autor:		Siddhartha Argollo
 * 
 * Copyright (C) TecnoTRENDS.  Todos os direitos reservados.
 =====================================================================*/
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace DaCredito
{
    /// <summary>
    /// Implementação de métodos utilitários para Collections.
    /// </summary>
    public static class CollectionUtils
    {
        // Separador padrão
        private const string SEPARATOR = ",";
        // Delimitadores padrão
        private const string DELIMITERS = "{}";

        /// <summary>
        /// Adiciona os elementos da string <c>asList</c>, separados por <c>asSep</c>
        /// na lista <c>aoList</c>.
        /// </summary>
        /// <param name="asList">String contendo os elementos.</param>
        /// <param name="asSep">Separador dos elementos.</param>
        /// <param name="aoList">Lista que irá receber os elementos.</param>
        public static void FromString(string asList, string asSep, IList aoList)
        {
            int liPos = asList.IndexOf(asSep);
            while (liPos > 0)
            {
                string lsStr = asList.Substring(0, liPos);
                asList = asList.Substring(liPos + 1);
                aoList.Add(lsStr);
                liPos = asList.IndexOf(asSep);
            }
            if (!StringUtils.IsEmpty(asList))
                aoList.Add(asList);
        }

        /// <summary>
        /// Retorna os elementos da coleção em forma de string, separados
        /// por vírgula.
        /// </summary>
        /// <remarks>
        /// O objeto <c>aoList</c> pode ser um IList, IDictionary ou um
        /// ICollection.
        /// </remarks>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <returns>String contendo os elementos da coleção separados
        /// por vírgula.</returns>
        public static string ToString(ICollection aoList)
        {
            return ToString(aoList, SEPARATOR);
        }

        /// <summary>
        /// Retorna os elementos da coleção em forma de string, separados
        /// por <c>asSep</c>.
        /// </summary>
        /// <remarks>
        /// O objeto <c>aoList</c> pode ser um IList, IDictionary ou um
        /// ICollection.
        /// </remarks>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <returns>String contendo os elementos da coleção separados
        /// por <c>asSep</c>.</returns>
        public static string ToString(ICollection aoList, string asSep)
        {
            if (aoList is IList)
                return ToString((IList)aoList, asSep);
            if (aoList is IDictionary)
                return ToString((IDictionary)aoList, asSep);
            return ToString((IEnumerable)aoList, asSep);
        }

        /// <summary>
        /// Retorna os elementos da lista em forma de string, separados
        /// por vírgula.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por vírgula.</returns>
        public static string ToString(IList aoList)
        {
            return ToString(aoList, SEPARATOR);
        }

        /// <summary>
        /// Retorna os elementos da lista em forma de string, separados
        /// por <c>asSep</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por <c>asSep</c>.</returns>
        public static string ToString(IList aoList, string asSep)
        {
            return ToString(aoList, asSep, "");
        }

        /// <summary>
        /// Retorna os elementos da lista em forma de string, separados
        /// por <c>asSep</c> e delimitados por <c>asDelim</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <param name="asDelim">Delimitadores a serem utilizados na
        /// string final. Deve conter dois caracteres, como por 
        /// exemplo: {}, [], (), etc.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por <c>asSep</c> e delimitados por <c>asDelim</c>.</returns>
        public static string ToString(IList aoList, string asSep, string asDelim)
        {
            StringBuilder loText = new StringBuilder();
            if (asDelim.Length >= 1)
                loText.Append(asDelim[0]);
            for (int i = 0; i < aoList.Count; i++)
            {
                loText.Append(GetValue(aoList[i], asSep, asDelim));
                if (i < aoList.Count - 1)
                    loText.Append(asSep);
            }
            if (asDelim.Length > 1)
                loText.Append(asDelim[1]);
            return loText.ToString();
        }

        /// <summary>
        /// Retorna os elementos do dicionário em forma de string, cada
        /// elemento no formato key=value, separados vírgula.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por vírgula.</returns>
        public static string ToString(IDictionary aoList)
        {
            return ToString(aoList, SEPARATOR);
        }

        /// <summary>
        /// Retorna os elementos do dicionário em forma de string, cada
        /// elemento no formato key=value, separados por <c>asSep</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por <c>asSep</c>.</returns>
        public static string ToString(IDictionary aoList, string asSep)
        {
            return ToString(aoList, asSep, "", null);
        }

        /// <summary>
        /// Retorna os elementos do dicionário em forma de string, cada
        /// elemento no formato key=value, separados por <c>asSep</c> e 
        /// delimitados por <c>asDelim</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <param name="asDelim">Delimitadores a serem utilizados na
        /// string final. Deve conter dois caracteres, como por 
        /// exemplo: {}, [], (), etc.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por <c>asSep</c> e delimitados por <c>asDelim</c>.</returns>
        public static string ToString(IDictionary aoList, string asSep, string asDelim)
        {
            return ToString(aoList, asSep, asDelim, "");
        }

        /// <summary>
        /// Retorna os elementos do dicionário em forma de string, cada
        /// elemento no formato key=value, separados por <c>asSep</c> e 
        /// delimitados por <c>asDelim</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <param name="asDelim">Delimitadores a serem utilizados na
        /// string final. Deve conter dois caracteres, como por 
        /// exemplo: {}, [], (), etc.</param>
        /// <param name="asExclude">Parâmetro opcional. Se existir, será
        /// utilizado para excluir da string resultante todas as chaves
        /// que se iniciarem com a string <c>asExclude</c>.</param>
        /// <returns>String contendo os elementos da lista separados
        /// por <c>asSep</c> e delimitados por <c>asDelim</c>.</returns>
        public static string ToString(IDictionary aoList, string asSep, string asDelim,
          string asExclude)
        {
            StringBuilder loText = new StringBuilder();
            if (asDelim.Length >= 1)
                loText.Append(asDelim[0]);
            foreach (DictionaryEntry loEntry in aoList)
            {
                if (!StringUtils.IsEmpty(asExclude) && loEntry.Key.ToString().StartsWith(asExclude))
                    continue;
                loText.Append(string.Format("{0}={1}", loEntry.Key, GetValue(loEntry.Value, asSep, asDelim)));
                loText.Append(asSep);
            }
            if (asDelim.Length > 1)
                loText.Append(asDelim[1]);
            if (loText.Length > 0)
                return loText.ToString(0, loText.Length - asSep.Length);
            return "";
        }

        /// <summary>
        /// Retorna os elementos da lista enumerada em forma de 
        /// string, separados por vírgula.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <returns>String contendo os elementos da lista enumerada 
        /// separados por vírgula.</returns>
        public static string ToString(IEnumerable aoList)
        {
            return ToString(aoList, SEPARATOR);
        }

        /// <summary>
        /// Retorna os elementos da lista enumerada em forma de 
        /// string, separados por <c>asSep</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <returns>String contendo os elementos da lista enumerada 
        /// separados por <c>asSep</c>.</returns>
        public static string ToString(IEnumerable aoList, string asSep)
        {
            return ToString(aoList, asSep, "");
        }

        /// <summary>
        /// Retorna os elementos da lista enumerada em forma de 
        /// string, separados por <c>asSep</c> e delimitados por 
        /// <c>asDelim</c>.
        /// </summary>
        /// <param name="aoList">Lista a ser utilizada.</param>
        /// <param name="asSep">Separador a ser utilizado.</param>
        /// <param name="asDelim">Delimitadores a serem utilizados na
        /// string final. Deve conter dois caracteres, como por 
        /// exemplo: {}, [], (), etc.</param>
        /// <returns>String contendo os elementos da lista enumerada 
        /// separados por <c>asSep</c> e delimitados por <c>asDelim</c>.
        /// </returns>
        public static string ToString(IEnumerable aoList, string asSep, string asDelim)
        {
            StringBuilder loText = new StringBuilder();
            if (asDelim.Length >= 1)
                loText.Append(asDelim[0]);
            foreach (object loValue in aoList)
                loText.Append(GetValue(loValue, asSep, asDelim)).Append(asSep);
            if (loText.Length > 0)
                loText.Remove(loText.Length - asSep.Length, asSep.Length);
            if (asDelim.Length > 1)
                loText.Append(asDelim[1]);
            return loText.ToString();
        }

        public static void CopyTo(IList aoSource, IList aoDest)
        {
            if (!aoDest.GetType().IsArray)
                aoDest.Clear();
            for (int i = 0; i < aoSource.Count; i++)
                if (aoDest.GetType().IsArray)
                    aoDest[i] = aoSource[i];
                else
                    aoDest.Add(aoSource[i]);
        }

        // Processa o valor, retornando uma string se o este for uma coleção
        private static string GetValue(object loValue, string asSep, string asDelim)
        {
            string lsValue;
            if (loValue == null)
                lsValue = "null";
            else if (loValue is string)
                lsValue = (string)loValue;
            else if (loValue is IList)
                lsValue = CollectionUtils.ToString((IList)loValue, asSep, asDelim);
            else if (loValue is IDictionary)
                lsValue = CollectionUtils.ToString((IDictionary)loValue, asSep, asDelim);
            else if (loValue is IEnumerable)
                lsValue = CollectionUtils.ToString((IEnumerable)loValue, asSep, asDelim);
            else
                lsValue = loValue.ToString();
            return lsValue;
        }

        public static bool Equals(IList aoList1, IList aoList2)
        {
            if (aoList1.Count != aoList2.Count)
                return false;
            for (int i = 0; i < aoList1.Count; i++)
            {
                if (!aoList1[i].Equals(aoList2[i]))
                    return false;
            }
            return true;
        }

    } // Collections

} // Trends.TFC.Util
